<template>
  <div class="ace-container">
    <div ref="editorRef" class="ep-ace-editor" />
  </div>
</template>

<script>
import { onMounted, onBeforeUnmount, ref, computed, watch } from 'vue'
import ace from 'ace-builds'
import 'ace-builds/src-min-noconflict/mode-text'
import 'ace-builds/src-min-noconflict/theme-chrome' // 导入主题
import 'ace-builds/src-min-noconflict/ext-language_tools' // 可选，代码提示等功能

export default {
  name: 'CodeEditorFormula',
  props: {
    modelValue: {
      type: String,
      default: ''
    }
  },
  emits: ['update:modelValue'],
  setup(props, { emit }) {
    let editor = null
    const editorRef = ref(null)
    const codeValue = computed(() => props.modelValue)

    const options = {
      mode: `ace/mode/text`, // 设置语法模式
      theme: 'ace/theme/chrome', // 设置主题
      fontSize: 14, // 字体大小
      showPrintMargin: false, // 隐藏边线
      showGutter: false, // 不显示行号
      enableBasicAutocompletion: true, // 启用自动补全
      enableLiveAutocompletion: true, // 实时补全
      maxLines: 18, // 最大行数，超过会自动出现滚动条
      minLines: 18, // 最小行数，还未到最大行数时，编辑器会自动伸缩大小
      tabSize: 2, // 制表符设置为2个空格大小
      highlightActiveLine: true,
      value: codeValue.value
    }

    // 定义自定义高亮规则
    const defineCustomHighlightRules = () => {
      const oop = ace.require('ace/lib/oop')
      const TextHighlightRules = ace.require('ace/mode/text_highlight_rules').TextHighlightRules

      const CustomHighlightRules = function () {
        // 定义所有函数名（关键字）
        this.functionKeywords = [
          // 逻辑函数
          'IF',
          'AND',
          'OR',
          'NOT',
          'XOR',
          // 比较函数
          'EQ',
          'NE',
          'GT',
          'GE',
          'LT',
          'LE',
          // 数学函数
          'ADD',
          'SUB',
          'MUL',
          'DIV',
          'MOD',
          'POW',
          // 循环函数
          'SUM',
          'PRODUCT',
          'COUNT',
          'AVERAGE',
          'MIN',
          'MAX',
          // 日期函数
          'DATE',
          'DATEDIFF',
          'DAY',
          'MONTH',
          'YEAR',
          // 文本函数
          'CONCAT',
          'LEN',
          'LEFT',
          'RIGHT',
          // 数组函数
          'MAP',
          'FILTER',
          'REDUCE',
          'ARRAY'
        ]

        // 构建函数名的正则表达式
        var functionRegex = '\\b(' + this.functionKeywords.join('|') + ')\\b'

        // 定义高亮规则
        this.$rules = {
          start: [
            {
              token: 'entity.name.function', // 表单属性（变量）
              regex: '\\{[^{}]+\\}'
            },
            {
              token: 'keyword', // 函数名
              regex: functionRegex
            },
            {
              token: 'keyword', // 括号
              regex: '[\\[\\(\\{\\)\\}\\]]'
            },
            {
              token: 'variable.parameter', // 参数（变量）
              regex: '[a-zA-Z_$][a-zA-Z0-9_$]*'
            },
            {
              token: 'string', // 字符串
              regex: '"(?:[^"\\\\]|\\\\.)*"'
            },
            {
              token: 'comment', // 注释
              regex: '//.*$',
              next: 'start'
            },
            {
              token: 'comment', // 多行注释
              regex: '/\\*',
              next: 'comment'
            },
            {
              token: 'comment', // 多行注释结束
              regex: '\\*/',
              next: 'start'
            },
            {
              token: 'constant.language.boolean', // 布尔值
              regex: '\\b(?:true|false)\\b'
            },
            {
              token: 'constant.numeric', // 数字
              regex: '\\b\\d+(\\.\\d+)?\\b'
            },
            {
              token: 'keyword.operator', // 操作符
              regex: '[=<>!&|\\+\\-\\*/%]'
            },
            {
              token: 'comma', // 逗号
              regex: ','
            }
          ]
        }
      }

      oop.inherits(CustomHighlightRules, TextHighlightRules)
      return CustomHighlightRules
    }

    // 定义自定义模式
    const defineCustomMode = (CustomHighlightRules) => {
      const oop = ace.require('ace/lib/oop')
      const TextMode = ace.require('ace/mode/text').Mode

      const Mode = function () {
        this.HighlightRules = CustomHighlightRules
      }

      oop.inherits(Mode, TextMode)
      return Mode
    }

    watch(codeValue, (val) => {
      if (editor && val !== editor.getValue()) {
        editor.setValue(val)
      }
    })

    onMounted(() => {
      ace.config.set('basePath', 'https://fastly.jsdelivr.net/npm/ace-builds@1.32.3/src-noconflict/')
      editor = window.ace.edit(editorRef.value, options)

      // 2. 创建自定义语法
      const CustomHighlightRules = defineCustomHighlightRules()
      const CustomMode = defineCustomMode(CustomHighlightRules)

      // 3. 设置自定义模式
      const customMode = new CustomMode()
      editor.session.setMode(customMode)

      // 数据更新
      editor.on('change', () => {
        if (emit) {
          emit('update:modelValue', editor.getValue())
        }
      })
    })
    onBeforeUnmount(() => {
      editor.destroy()
      editor.container.remove()
    })

    // 插入数据
    const insertValue = (text) => {
      const cursor = editor.getCursorPosition()
      editor.session.insert(cursor, String(text))
    }

    // 覆盖内容
    const setValue = (text) => {
      editor.session.setValue(String(text))
    }

    // 获取焦点指定位置
    const focus = (n = 0) => {
      const { row, column } = editor.getCursorPosition()
      editor.focus()
      editor.gotoLine(row + 1, column + n)
    }
    return { editorRef, insertValue, setValue, focus }
  }
}
</script>
